package com.utoronto.syncgallery.utils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.media.ThumbnailUtils;
import android.util.Log;

import com.utoronto.syncgallery.GalleryActivity;

/**
 * FileManagement is the class to handle files.
 * 
 * @author Kobe Sun, Daniel
 * 
 */

public class ImageManagement {

	private static String extension;

	/** Move the selected file to SyncGallery folder. */
	public static boolean move_to_gallery(GalleryActivity gallery, File file) {

		boolean result;

		/** File does not exist. */
		if (!file.exists() || !file.isFile()) {
			show_dialog(gallery, "Rename", "Not a valid file!");
			return false;
		}

		if (!file.canWrite()) {
			show_dialog(gallery, "Move to SyncGallery",
					"The current file is not writable!");
		}

		/** Check the SyncGallery folder. If it does not exist, create it. */
		File destDir = new File(SyncGalleryConstants.Gallery_ENTRY_DIR);
		if (!destDir.exists())
			destDir.mkdirs();

		/** Path for writing. */
		String path = SyncGalleryConstants.Gallery_SYNC_DIR + File.separator
				+ file.getName();

		/** The path is valid. */

		if (new File(path).exists()) {
			/** A same name file already exists in SyncGallery folder. */
			show_dialog(gallery, "Move to SyncGallery",
					"A file with the same name already exists in the current folder!");
			return false;
		} else {
			/** Rename the file. */
			delete_thumbnail(gallery, file);
			result = file.renameTo(new File(path));
			if (result == false) {
				show_dialog(gallery, "Move", "Move failed!");
				return false;
			}
			return result;
		}
	}

	/** Rename the file with new file name newname. */
	public static boolean rename(GalleryActivity gallery, File file,
			String newname) {

		/** File does not exist. */
		if (!file.exists() || !file.isFile())
			return false;

		if (newname.equals("")) {
			show_dialog(gallery, "Rename", "File name cannot be empty!");
			return false;
		}

		/** Return Error if there is invalid input string. */
		for (int i = 0; i < (SyncGalleryConstants.Gallery_RESERVEDCHARS)
				.length(); i++) {
			if (newname.contains(SyncGalleryConstants.Gallery_RESERVEDCHARS
					.substring(i, i + 1))) {
				show_dialog(gallery, "Rename",
						"New name contains invalid characters!");
				return false;
			}
		}

		/** Get file extension. */
		getExtension(file.getName());

		String path = file.getParentFile().getAbsolutePath() + File.separator
				+ newname + extension;

		if (new File(path).exists()) {
			/** A same name file already exists in SyncGallery folder. */
			show_dialog(gallery, "Rename",
					"A file with the same name already exists in the current folder!");
			return false;
		} else {
			/** Rename the file. */
			return file.renameTo(new File(file.getParentFile()
					.getAbsolutePath() + File.separator + newname + extension));
		}
	}

	/** Rename the the thumbnail of the file with new file name newname. */
	public static boolean rename_thumbnail(GalleryActivity gallery, File file,
			String newname) {

		/** Get thumbnail path. */
		File thumbnail = new File(file.getParentFile().getAbsolutePath()
				+ SyncGalleryConstants.Gallery_THUMBNAILS + file.getName());

		/** Move the file. */
		return rename(gallery, thumbnail, newname);
	}

	/** Get the file extension. */
	public static void getExtension(String filename) {

		/** Check last index start before ".". */
		if ((filename != null) && (filename.length() > 0)) {
			int i = filename.lastIndexOf('.');

			/** Save the extension string. */
			if ((i > -1) && (i < (filename.length() - 1))) {
				extension = '.' + filename.substring(i + 1);
			}
		}
	}

	/** Helper function to get the thumbnail */
	public static final Bitmap getImageThumbnail(File file) {

		/** Set bitmap size. */
		BitmapFactory.Options options = new BitmapFactory.Options();
		options.inSampleSize = 4;

		File thumbfile = new File(file.getParentFile().getAbsolutePath()
				+ SyncGalleryConstants.Gallery_THUMBNAILS + file.getName());
		if (thumbfile.exists()) {
			/** Retrieve from the thumbnail folder */
			return BitmapFactory.decodeFile(thumbfile.getAbsolutePath());
		} else {
			/** Create the thumbnail based on orignal image */
			Bitmap image = BitmapFactory.decodeFile(file.getAbsolutePath(),
					options);
			Bitmap thumbnail = ThumbnailUtils.extractThumbnail(image, 100, 100);
			if (thumbnail != null) {
				/** Save it to thumbnail folder for future use */
				saveBitMap(thumbnail, file);
			}
			return thumbnail;
		}
	}

	/** Save the bitmap to the thumbnail folder */
	public static final void saveBitMap(Bitmap thumbnail, File file) {

		/** Get thumbnail folder directory. */
		File dir = new File(file.getParentFile().getAbsolutePath()
				+ SyncGalleryConstants.Gallery_THUMBNAILS);

		/** thumbnails folder does not exist. */
		if (!dir.exists())
			dir.mkdirs();

		/** Try to compress and save it. */
		try {
			File outfile = new File(dir, file.getName());
			FileOutputStream fOut = new FileOutputStream(outfile);
			thumbnail.compress(Bitmap.CompressFormat.JPEG, 30, fOut);
			fOut.flush();
			fOut.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/** Delete selected image. */
	public static void delete(final GalleryActivity gallery, final File file) {

		/** Set the UI interface. */
		final AlertDialog alertDialog = new AlertDialog.Builder(gallery)
				.create();

		/** The user chooses to delete. */
		final OnClickListener listener1 = new OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				delete_thumbnail(gallery, file);
				if (!file.delete()) {
					show_dialog(gallery, "Delete", "Deletion failed!");
				}
				//
				/** Refresh the current directory. */
				gallery.browseTo(file.getParentFile());
			}
		};

		/** The user cancels their operation. */
		final OnClickListener listener2 = new OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				alertDialog.cancel();
			}
		};

		/** Show the dialog. */
		alertDialog.setTitle("Delete");
		alertDialog.setMessage("Are you sure?");
		alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, "OK", listener1);
		alertDialog.setButton(AlertDialog.BUTTON_NEGATIVE, "Cancel", listener2);
		alertDialog.show();
	}

	/** Delete thumbnail associated with the images. */
	public static void delete_thumbnail(GalleryActivity gallery, File file) {
		File thumbnail = new File(file.getParentFile().getAbsolutePath()
				+ SyncGalleryConstants.Gallery_THUMBNAILS + file.getName());
		if (!thumbnail.delete()) {
			show_dialog(gallery, "Delete", "Thumbnail is not deleted!");
		}
	}

	/** Show file information. */
	public static void show_properties(GalleryActivity gallery, File file) {
		String title = "Properties";
		String filename = "File Name: " + file.getName() + "\n";
		String path = "Path: " + file.getAbsolutePath() + "\n";
		String size = "Size: " + convert(file.length(), true) + "\n";
		String msg = filename + path + size;
		show_dialog(gallery, title, msg);
	}

	/** Convert the file size. */
	public static String convert(long bytes, boolean si) {
		int unit = si ? 1000 : 1024;
		if (bytes < unit)
			return bytes + " B";
		int exp = (int) (Math.log(bytes) / Math.log(unit));
		String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1)
				+ (si ? "" : "i");
		return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
	}

	/** Helper function to show error messages. */
	public static void show_dialog(GalleryActivity gallery, String title,
			String msg) {
		final AlertDialog alertDialog = new AlertDialog.Builder(gallery)
				.create();
		final OnClickListener listener1 = new OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				alertDialog.cancel();
			}
		};
		alertDialog.setTitle(title);
		alertDialog.setMessage(msg);
		alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, "OK", listener1);
		alertDialog.show();
	}

	public static String generateDCIMFilename() {
		Calendar cal = Calendar.getInstance();
		SimpleDateFormat date = new SimpleDateFormat("yyyyMMdd");
		SimpleDateFormat time = new SimpleDateFormat("Hmmss");
		return "IMG_" + date.format(cal.getTime()) + "_"
				+ time.format(cal.getTime()) + ".jpg";
	}

	public static final void rotateImage(File image, int rotation) {
		Bitmap bm = createOptimizedBitMap(image);
		Matrix matrix = new Matrix();
		matrix.postRotate(rotation);
		Bitmap out = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),
				bm.getHeight(), matrix, true);
		try {
			File outfile = new File(image.getParentFile(), image.getName());
			FileOutputStream fOut = new FileOutputStream(outfile);
			out.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
			fOut.flush();
			fOut.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static final Bitmap createOptimizedBitMap(File image) {
		BitmapFactory.Options options = new BitmapFactory.Options();
		Log.i("KOBE", image.length() + "");
		options.inSampleSize = (int) (image.length() / (512 * 1024)) + 1;
		Log.i("KOBE-Size", options.inSampleSize + "");
		return BitmapFactory.decodeFile(image.getAbsolutePath(), options);
	}
}
